package com.tark.service.qrcode.service;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Hashtable;
import java.util.Map;

import javax.imageio.ImageIO;

import org.springframework.stereotype.Service;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.multi.qrcode.QRCodeMultiReader;
import com.tark.service.qrcode.pojo.QrcodePojo;
@Service
public class QrcodeServiceImp implements QrcodeService {

		
//生成没有LOGO的 二维码
	@Override
	public  String generateQrcode(QrcodePojo Qrcode) {
		//我要的 二维码 都是正方形的 这里我就让用户给个尺寸 我自己搞成正方形
		int width=Qrcode.getLength().intValue();
		int height=Qrcode.getLength().intValue();
		//二维码内容
		String content= Qrcode.getContent();
		//获取文件后缀名
		String suffix=Qrcode.getSuffixName();
		//文件名  用户给的 存盘路径 basepath 品尚 我的文件名 带后缀的 FileName
        File imageFile = new File(Qrcode.getBasePath(), Qrcode.getFileName());
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        // 指定纠错等级                                                                                pojo对象中写死的 静态参数 直接拿
        hints.put(EncodeHintType.ERROR_CORRECTION, QrcodePojo.getLevel());
        // 指定编码格式
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 设置白边                                                                                       pojo对象中写死的 静态参数 直接拿
        hints.put(EncodeHintType.MARGIN, QrcodePojo.getMargin());   
        try {
            MatrixToImageConfig config = new MatrixToImageConfig(QrcodePojo.getOnColor(),QrcodePojo.getOffColor());
            BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            //bitMatrix = deleteWhite(bitMatrix);
            MatrixToImageWriter.writeToPath(bitMatrix, suffix, imageFile.toPath(), config);
        } catch (Exception e) {
            e.printStackTrace();
        }				
		return Qrcode.getBasePath()+Qrcode.getFileName();
	}


	 /**
     * 生成带logo的二维码图片
     *
     * @param content      //二维码内容
     * @param logoPath //logo绝对物理路径
     * @param imgPath  //二维码保存绝对物理路径
     * @param imgName  //二维码文件名称
     * @param suffix   //图片后缀名
     * @throws Exception
     */
    public static void generateQRImage(QrcodePojo qrcodePojo,String imgPath) throws Exception {
    	String content = qrcodePojo.getContent();

    	Integer length = qrcodePojo.getLength();
    	int width=length.intValue();
    	int height=length.intValue();
    	String logoPath = qrcodePojo.getLogoFullPath();
    	String suffix=qrcodePojo.getSuffixName();
    	
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hints.put(EncodeHintType.ERROR_CORRECTION, QrcodePojo.getLevel());
        hints.put(EncodeHintType.MARGIN, QrcodePojo.getMargin());  //设置白边
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        File qrcodeFile = new File(qrcodePojo.getBasePath()+File.separator+qrcodePojo.getFileName());
        System.out.println(qrcodeFile.toString());
        writeToFile(bitMatrix, suffix, qrcodeFile, logoPath);
    }

    /**
     * @param matrix   二维码矩阵相关
     * @param format   二维码图片格式
     * @param file     二维码图片文件
     * @param logoPath logo路径
     * @throws IOException
     */
    public static void writeToFile(BitMatrix matrix, String format, File file, String logoPath) throws IOException {
        BufferedImage image = toBufferedImage(matrix);
        Graphics2D gs = image.createGraphics();

        int ratioWidth = image.getWidth() * 2 / 10;
        int ratioHeight = image.getHeight() * 2 / 10;
        //载入logo
        Image img = ImageIO.read(new File(logoPath));
        int logoWidth = img.getWidth(null) > ratioWidth ? ratioWidth : img.getWidth(null);
        int logoHeight = img.getHeight(null) > ratioHeight ? ratioHeight : img.getHeight(null);

        int x = (image.getWidth() - logoWidth) / 2;
        int y = (image.getHeight() - logoHeight) / 2;

        gs.drawImage(img, x, y, logoWidth, logoHeight, null);
        gs.setColor(Color.black);
        gs.setBackground(Color.WHITE);
        gs.dispose();
        img.flush();
        if (!ImageIO.write(image, format, file)) {
            throw new IOException("Could not write an image of format " + format + " to " + file);
        }
    }

    public static BufferedImage toBufferedImage(BitMatrix matrix) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? QrcodePojo.getOnColor() : QrcodePojo.getOffColor());
            }
        }
        return image;
    }

    public static BitMatrix deleteWhite(BitMatrix matrix) {
        int[] rec = matrix.getEnclosingRectangle();
        int resWidth = rec[2] + 1;
        int resHeight = rec[3] + 1;

        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
        resMatrix.clear();
        for (int i = 0; i < resWidth; i++) {
            for (int j = 0; j < resHeight; j++) {
                if (matrix.get(i + rec[0], j + rec[1]))
                    resMatrix.set(i, j);
            }
        }
        return resMatrix;
    }	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	@Override
	public String readQrcode(String fullFilePath) throws Exception {
		  File whatFile = new File(fullFilePath);
	      Map<DecodeHintType,Object> whatHints = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
	        whatHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
	        whatHints.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.allOf(BarcodeFormat.class));
	        whatHints.put(DecodeHintType.PURE_BARCODE, Boolean.FALSE);
				
			 if (whatFile == null || whatFile.getName().trim().isEmpty())
	             throw new IllegalArgumentException("File not found, or invalid file name.");
	         BufferedImage tmpBfrImage;
	         try 
	         {
	             tmpBfrImage = ImageIO.read(whatFile);
	         } 
	         catch (IOException tmpIoe) 
	         {
	             throw new Exception(tmpIoe.getMessage());
	         }
	         if (tmpBfrImage == null)
	             throw new IllegalArgumentException("Could not decode image.");
	         LuminanceSource tmpSource = new BufferedImageLuminanceSource(tmpBfrImage);
	         BinaryBitmap tmpBitmap = new BinaryBitmap(new HybridBinarizer(tmpSource));
	         QRCodeMultiReader tmpBarcodeReader = new QRCodeMultiReader();
	         Result[] tmpResult;
	         String tmpFinalResult = null;
	         try 
	         {
	             if (whatHints != null && ! whatHints.isEmpty())
	                 tmpResult = tmpBarcodeReader.decodeMultiple(tmpBitmap, whatHints);
	             else
	                 tmpResult = tmpBarcodeReader.decodeMultiple(tmpBitmap);
	             // setting results.
	             for (Result result : tmpResult) {
	            	 tmpFinalResult=String.valueOf(result.getText());
				}
	         } 
	         catch (Exception tmpExcpt) 
	         {
	             throw new Exception("BarcodeService readBarcode Excpt err - " + tmpExcpt.toString() + " - " + tmpExcpt.getMessage());
	         }
	         return tmpFinalResult;
		}
	}


